home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / PMTUT.ZIP / CPUMODES.ZIP / CPUMODES
Encoding:
Text File  |  1995-06-08  |  18.3 KB  |  331 lines

  1. It is preliminary version of text to put in x86 FAQ (it was
  2. also sent to alt.lang.asm, seems this group is more appropriate).
  3. Please send me suggestions what improvement would be useful.
  4.  
  5.  
  6. Real and Protected Modes.
  7.  
  8. Beginning from 80286, Intel CPUs have ability to work in Protected Mode
  9. (older CPUs have Real Mode only). For compatibility reasons, all CPUs
  10. start in Real Mode after reset. Below are presented main differences
  11. between Real Mode and Protected modes for Intel CPUs. Note there are:
  12. Real Mode, Protected Mode, Virtual 8086 Mode (they will be frequently
  13. called RM, PM, VM86, respectively; also 286+(386+) will mean Intel
  14. 80286(80386) or better).
  15.  
  16. There are some differences between these modes in memory addressing
  17. (PM can address all memory, while RM can't unless it is set in PM on
  18. 386+, and VM86 cannot unless using PM supporting it to remap memory
  19. - this way EMM386 works); instruction set (some instruction are not
  20. allowed in RM), privileges (something can be forbidden in PM for less
  21. privileged code, many operations are forbidden in VM86), interrupt
  22. handling. PM supports multitasking, PM can run tasks in VM86 (the
  23. VM86 cannot function alone, must have PM code supporting it; it works
  24. similarly 8086 CPU with few enhancements except interrupt servicing
  25. which goes through PM). PM cannot store data to code segment (unless
  26. by aliasing; MOV CS:[BX],AX is illegal in PM). VM86 and PM on 386+ can
  27. have selective I/O port access restrictions (some ports can be accessed
  28. without causing exception and other can't).
  29.  
  30.  
  31. Memory addressing and Paging.
  32.  
  33. In any mode, opcode defines some offset and segment of referenced memory
  34. address, e.g. mov ax,es:[bx+si+1] - segment es, offset bx+si+1, push si
  35. - segment ss, offset sp-2, opcode itself is referenced by segment cs and
  36. offset ip; the address is translated to Linear Address by adding the
  37. offset to base of the segment and the Linear Address is then translated
  38. to Physical Address which is outputed by CPU on its address pins.
  39.  
  40. In RM or VM86, the base is segment*10h; in PM the base is taken from
  41. descriptor table (LDT or GDT) and can have any value.
  42. The value in segment register is called "selector" and its bits 15-3
  43. specify offset in LDT or GDT (the offset is multiply of 8), bit 2 is 0
  44. for GDT, 1 for LDT, bits 1-0 specify RPL (Requested Privilege Level).
  45.  
  46. Unless Paging (possible in PM and VM86, on 386+ only) is enabled,
  47. Physical Address = Linear. With Paging, low 12 bits of Linear Address
  48. go to Physical, other are used as index to two-level page tables
  49. (first bits 31-22 select page directory, then bits 21-12 select page).
  50.  
  51. Paging can also restrict access to some pages (in a way non-privileged
  52. code can read it only or has no access at all), or define non-present
  53. pages which have assigned physical addresses and put in memory in a way
  54. transparent to program when access to their Linear Address is attempted.
  55. Note Linear Address space is 4GB on 386+, and probably no system has so
  56. much physical memory: Paging makes system able to simulate it has.
  57.  
  58. Segment has also limit. Initially, the limit is 0FFFFh for all segment
  59. registers and cannot be changed in RM or VM86. In PM it is loaded from
  60. LDT or GDT when segment register is loaded. On 286 in PM the limit can
  61. be up to 0FFFFh, on 386+ in PM it can be up to 0FFFFFFFFh.
  62. Also, PM allows "expand down" segments which allow access from address
  63. limit+1 to maximum possible value of limit (depend on segment type).
  64.  
  65.  
  66. Privilege Levels and Rules.
  67.  
  68. In RM, CPU has full privileges. In PM and VM86, they can be restricted.
  69. This reduces possibility of making disasters by bad code.
  70.  
  71. Base rules: cannot access more privileged data or call less privileged
  72. code than own privilege (although can return to less privileged code).
  73. Additional: call to more privileged code cannot use any target address
  74. caller wants, it can use addresses specified by system only; call to
  75. more privileged code must change stack to make sure enough stack space
  76. is available for called code (so caller cannot cause crash in it).
  77.  
  78. There are 4 levels: level 0 is full privilege (except Debug Registers,
  79. which can be protected from access even from level 0; some instructions
  80. are reserved for level 0 only), the bigger level the less privileges
  81. are. Few terms used for Privilege Levels: CPL - Current PL, DPL -
  82. Descriptor PL, RPL - Requested PL (in selector), IOPL (in flags) -
  83. max CPL allowing I/O sensitive opcodes (CLI, STI, PUSHF, POPF,...).
  84.  
  85. Unless accessing Conforming Code segment, privilege rules require
  86. max(CPL,RPL)<=DPL. To execute code (by FAR CALL or JMP) need DPL<=CPL
  87. (note unless it is Conforming, must be DPL=CPL and RPL<=CPL) - cannot
  88. call less privileged procedure, for example. To transfer control to
  89. code with less PL (more privileged), must CALL via call gate (in such
  90. a case, need max(CPL,RPL)<=gate_DPL, but for code the gate refers to
  91. may be code_DPL<gate_DPL; the gate is entry in GDT or LDT; privilege
  92. rules require also target_code_DPL <= CPL for CALL, = for JMP), this
  93. also requires TR to point to valid TSS because it switches stack: old
  94. SS:[E]SP are pushed on new stack, then parameters (as defined in call
  95. gate) are pushed, finally CS:[E]IP are pushed. On return from the call
  96. CPU detects RPL of CS on stack > CPL and switches stack back (if =, no
  97. stack switch, < inhibited by privilege rules), for proper functioning
  98. parameter counts on RET and in call gate must match. For stack segment
  99. DPL must be equal CPL (so in more privileged mode no crash is possible
  100. due to incorrect stack setting in less privileged, and in the less
  101. privileged there is no access to more privileged mode stack).
  102.  
  103. The RPL is for system to block possibility to pass a pointer from user
  104. code which is invalid in user mode and valid in system: system uses RPL
  105. as for user code and gets access violation error in such a case.
  106. It can be done using ARPL opcode which adjusts RPL for a selector, and
  107. sets ZF if changed (to inform OS invalid access might be attempted).
  108. OS uses it to set RPL of the pointer to CPL of the application code.
  109.  
  110. It is possible to check what access having to a segment by opcodes like
  111. VERR, VERW, LAR, LSL. They all set ZF if having access, clear if not.
  112. First two simply verify R/W access, LAR gets bits defining access right
  113. for a segment, LSL gives the segment limit value. These opcodes allow
  114. checking what would cause access violation, instead getting the error.
  115.  
  116. Conforming code segments can be accessed without high privilege, they
  117. are for libraries which are shared between levels (otherwise would need
  118. keep separate copy for every level). Data kept in them can be accessed
  119. from any PL (providing they are readable) and code can be accessed (by
  120. jump or call) from same or less privileged PL - in such a case CPL is
  121. NOT changed by the jump or call. Cannot execute conforming code from
  122. more privileged PL: it is not trusteed enough to get CPL<DPL (greater
  123. privilege than defined in system tables).
  124. I'm not sure how return from non-conforming to conforming code works,
  125. seems RPL taken from CS on stack determines new CPL (which may be less
  126. privileged than the conforming code segment DPL).
  127.  
  128. Some instructions are allowed at CPL=0 only. They are:
  129. Clear Task─Switched Flag (CLTS), Halt Processor (HLT), loading some
  130. system registers (GDTR,IDTR,LDTR,MSW,TR), any access to CRx,DRx,TRx.
  131. Some other require CPL<=IOPL. They are: IN, INS, OUT, OUTS, CLI, STI.
  132. Also, POPF behavior depends on CPL: if CPL>0, IOPL and VM aren't
  133. changed by POPF, if CPL>IOPL, IF (interrupt enable) isn't changed.
  134.  
  135.  
  136. Interrupts.
  137.  
  138. In every mode, there is an array containing information what action is
  139. to be taken in case of interrupt. Its first entry corresponds to INT 0,
  140. next to INT 1, and so on. It is called IDT(Interrupt Descriptor Table).
  141. In RM, each entry in the IDT is simply far address of interrupt service
  142. routine. Initially IDT is located at address 0 and has 100h entries
  143. (400h bytes; some CPU-s have its limit 0FFFFh but the remainder isn't
  144. accessible in RM); on pre-80286 CPUs the IDT address and size cannot be
  145. changed, on 286+ can load and store them using LIDT and SIDT opcodes.
  146.  
  147. In PM the IDT has 8-byte entries which can be interrupt, trap or task
  148. gates. Trap differs from interrupt by leaving interrupt flag same as
  149. in interrupted code. Task gate causes calling another task. They all
  150. have DPLs and interrupt instruction causes General Protection error
  151. if CPL > interrupt or trap gate DPL. However, other interrupt sources
  152. have "CPL 0" - they can access any gate needed.
  153.  
  154. Some conditions can cause an Exception. They are (for 80386): divide
  155. error (0), debug exceptions (1), non-maskable interrupt (2), breakpoint
  156. (3), overflow (4, on into opcode), bounds check (5, on bound opcode),
  157. invalid opcode (6), coprocessor not available (7), double fault (8,E),
  158. coprocessor segment overrun (9,P), invalid TSS (10,PE), segment not
  159. present (11,PE), stack error (12,E), general protection error (13,E),
  160. page fault (14,PE), coprocessor error (16); marked by P can occur in
  161. PM and VM86 only, marked by E push error code on stack if they occur
  162. in PM or VM86 (so stack is: error, IP, CS, flags; the error code is
  163. usually either 0 or selector causing the exception (in case selector is
  164. invalid or non-accessible), with flags on low order bits: bit 0 means
  165. external source, bit 1 IDT selector, bit 2 LDT; for page fault it is
  166. set of flags (bits 3-31 undefined): bit 0 set if page protection
  167. violation, 1 if writing, 2 if user mode), most of them push IP of
  168. opcode causing them, except 3,4,9 which push IP of next opcode.
  169. Note: interrupt cannot be serviced at PL>CPL (unless via task switch),
  170. attempt to do it causes General Protection error.
  171.  
  172. Interrupt processing in PM is more complicated when interrupt handler
  173. has Privilege Level other than current code. It is handled similarly
  174. CALL via gate: stack is switched, new SS:SP are taken from TSS, old
  175. SS:SP are pushed on the new stack, then flags, CS, IP and eventually
  176. error code (for some exceptions) are pushed.
  177. In VM86 interrupt pushes GS,FS,DS,ES,SS,ESP,EFLAGS,CS,EIP (exception
  178. also error code) onto PL 0 stack. There is VM bit in EFLAGS set to tell
  179. interrupt occured in VM86. Note IDT must contain task gates and 80386
  180. trap or interrupt gates pointing to a non-conforming code segment with
  181. DPL=0 only - interrupt service must come through PL 0 or task switch.
  182. The VM86 itself has CPL 3 and is allowed in 386 task only.
  183.  
  184.  
  185. Descriptor Tables (PM only).
  186.  
  187. Global Descriptor Table(GDT) can contain descriptors of any type except
  188. interrupt and trap gates. It is necessary for PM. First entry in GDT
  189. isn't used - it corresponds to null selector which can be loaded into
  190. segment register but causes exception if used for memory addressing.
  191.  
  192. Local Descriptor Table(LDT) can contain "normal" segment descriptors
  193. (not e.g. TSS) and call or task gates only. Usually every task has its
  194. own LDT (changed on task switch). The LDT must have descriptor in GDT.
  195.  
  196. Interrupt Descriptor Table(IDT) was discussed in "Interrupts" section.
  197.  
  198. "Normal" segment descriptors are referenced when a segment register is
  199. loaded and they describe a memory area and give some access to it.
  200. Bit 2 of selector used selects table: 0 means GDT, 1 means LDT.
  201. Other descriptors can be Task State Segment(TSS), and gates. They can
  202. be referenced "as a code segment", e.g. by far jump or call and they
  203. cause transferring control to task or code segment referenced by them.
  204. It is kind of indirect jump or call (they contain target selector).
  205. TSS or gate pointing to TSS cause task switch. Gate can be used to
  206. transfer control to more privileged code not accessible directly.
  207. TSS can be also referenced by LTR (Load Task Register) opcode and it
  208. is done once during PM initialization. LDT descriptor can be loaded
  209. into LDTR(register) by LLDT opcode and usually it is done once.
  210.  
  211.  
  212. Segment and System Descriptors.
  213.  
  214. The following segment types (in byte [descriptor+5]) are supported
  215. (for all bit 7 means present in memory, bits 5-6 keep DPL which says
  216. what is maximum CPL which can access the descriptor, the restriction is
  217. for all descriptors, not segments only, except conforming segments):
  218.  
  219. 10h+flags    - data: bit 1 - writable, bit 2 - expand down
  220. 18h+flags    - code: bit 1 - readable, bit 2 - conforming
  221.  
  222. for both, bit 0 is set by any access. The descriptor also contains
  223. limit in word [0] (in 386 segments extended to bits 0-3 of byte [6])
  224. and base in bytes [2..4] (in 386 segments extended to byte [7]).
  225. Byte [6] keeps few additional flags: bit 7 - granularity (limit is in
  226. 4kB pages; e.g. limit 0 means 0..0FFFh accessible), bit 6 - 32-bit
  227. addressing (applies to code and stack - use EIP, ESP, makes expand down
  228. segment upper limit 4GB), bit 5 must be 0, bit 4 is for programmer.
  229.  
  230. 01h+flags    - TSS: bit 1 - busy, bit 3 - 386 TSS
  231. 02h        - LDT
  232. 04h+flags    - call gate
  233. 05h        - task gate
  234. 06h+flags    - interrupt gate: bit 0 - trap, bit 3 - 386.
  235.  
  236. for all gates, word[2] keeps selector, word[0] and word[3] keep offset
  237. of called code (ignored for task gate), byte[4] keeps word count (0-31)
  238. for copying in case of inter-level call (call gate only, else ignored);
  239. TSS and LDT have base and limit in same form as code and data segments
  240. have, they can have bit 7 set in byte [6] to specify limit in pages.
  241. Word [6] should be 0 for the descriptor to mean the same on 286/386.
  242.  
  243. LDT is similar GDT, except not all descriptor types are allowed.
  244. TSS holds entire task state (all registers: general, segment, flags,
  245. ip, ldtr); it also keeps link to caller TSS (valid if the task was
  246. activated by INT or CALL) and stacks (SS and [E]SP) for PL 0,1,2
  247. (they are used when more privileged code is invoked via gate from less
  248. privileged). 386 TSS has also debug trap bit (if set, causes INT 1 on
  249. task switch to the TSS), I/O bit map (saying which I/O addresses can
  250. be accessed when CPL>IOPL without General Protection exception), and
  251. CR3 value for the task (can remap memory on task switch).
  252.  
  253.  
  254. Page tables:
  255.  
  256. both page directory and page table entries keep referenced address in
  257. bits 31-12, have bits 11-9 reserved for programmer, must have bits 8,7,
  258. 4,3 set to 0; bit 5 is called A (accessed), it is set by CPU on access
  259. to the entry, bit 6 is called D (dirty), it is set if referenced memory
  260. is written; bit 0 is called P (present), all other are ignored if it is
  261. not set; bit 2 allows user (CPL=3) access if set, bit 1 allows user to
  262. write (together with bit 2 only), for CPL<3 read/write is allowed for
  263. any setting of bits 1 and 2 (no protection against system this way).
  264. Note page table entries used are usually cached by CPU: modifying them
  265. in memory may cause no mapping change until the cache is reloaded. The
  266. cache is flushed every time CR3 (which points to first page directory
  267. entry) is loaded. Bits 0-11 of CR3 must be 0 (directory page-aligned).
  268. Addressing through page tables: CR3+(Linear_Address SHR 20) AND 0FFCh
  269. is address in Page Directory, the entry at the address contains Page
  270. Table address; Page Table address + (Linear_Address SHR 10) AND 0FFCh
  271. is address in Page Table and the entry at the address contains base
  272. address of the page, combine it with bits 11-0 of Linear_Address and
  273. the result is Physical Address. In case of any error, CR2 is set to the
  274. Linear Address causing the error and error code explains what error.
  275. Note: if Paging is enabled, CR3 must keep Physical Address of Page
  276. Directory and all other addresses are Linear Addresses.
  277.  
  278.  
  279. Switching to Protected Mode or back to Real Mode:
  280.  
  281. First: to get control in case of crash, need store in dword [0467h]
  282. address where control is to be passed, and put 0Ah in CMOS register 0Fh
  283. (by CLI; MOV AL,8Fh; OUT 70h,AL; (1us delay) MOV AL,0Ah; OUT 71h,AL;).
  284. Also: normally, some circuitry in PC compatibles disables address line
  285. A20; must enable it. If you use HIMEM, it can be enabled by a request
  286. to HIMEM. If you also have DOS=HIGH, it is usually enabled, as it is
  287. enabled by any DOS call. In other cases, you must send output port
  288. value to keyboard controller to enable it before switching to PM.
  289.  
  290. Switch to PM: required is loading GDTR, then can enable protection by
  291. setting CR0/MSW bit 0 (MOV EAX,CR0; OR AL,1; MOV CR0,EAX; or SMSW AX;
  292. OR AL,1; LMSW AX; first on 386+, second on 286+); it is recommended
  293. to load IDTR immediately before or after mode switch (same IDT can't be
  294. valid in both modes); immediately after mode change should execute JMP
  295. to flush prefetch queue which may be partially decoded (the decoding
  296. may be mode dependent); need load CS and SS - they contain invalid
  297. selectors and e.g. interrupt causes them to be put on stack and crash
  298. on IRET; it is also recommended to load all segment registers (they can
  299. be loaded with 0 to contain invalid selector and cause exception if any
  300. of them is used to address memory) and LDTR; before first task switch
  301. must load TR (selector of valid free TSS descriptor; the TSS will be
  302. used to store state on task switch).
  303.  
  304. These is also a BIOS call which switches to PM and changes external
  305. interrupt vector mapping (normally 1st controller has 08h..0Fh, 2nd
  306. 70h..77h, the 1st conflicts with some CPU exceptions; however it is
  307. easy to distinguish external interrupt from an exception), it also
  308. enables address line A20. See INT 15h, AH=89h description.
  309.  
  310. Returning to RM: it can be done by clearing bit 0 in CR0 but it needs
  311. some preparation: must disable paging (go to code/stack which has
  312. linear addresses same as physical, clear PG bit in CR0, clear CR3), go
  313. to code segment with limit=64k and load all segment registers except
  314. CS with valid descriptor of 64kB read/write expand-up byte-granular
  315. present segment (attribute byte=93h, extended attribute=0) - otherwise
  316. you can get RM with e.g. read-only or 32kB ES, which will soon cause
  317. crash. After clearing the bit 0 of CR0 execute far jump to load CS and
  318. flush prefetch queue and load segment registers for RM.
  319.  
  320. This is not available on 80286 which has no CR0 register (the Protect
  321. Enable bit cannot be cleared by LMSW). The only way to get to RM again
  322. is resetting the CPU: it can be done by the following code: CLI;
  323. XOR CX,CX; wait_kbd_ctrlr_input_empty: IN AL,64h; TEST AL,2; LOOPNZ
  324. wait_kbd_ctrlr_input_empty; MOV AL,0FEh; OUT 64h,AL; HLT; or by CPU
  325. shutdown (resulting in case of exception while servicing double fault).
  326.  
  327. Note most programs running system in VM86 provide interface to switch
  328. to PM and back to VM86, it is called VCPI (Virtual Control Program
  329. Interface), can be tested for presence and invoked by INT 67h,AH=0DEh.
  330. It requires 3 entries in GDT to be reserved for VCPI provider.
  331.